/*
 * Copyright 2010-2012 Susanta Tewari. <freecode4susant@users.sourceforge.net>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package commons.util;

import commons.util.base.PairPredicate;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

/**
 * @author Susanta Tewari
 * @since Feb 6, 2012
 */
public class IterableUtil {

    /**
     * Constructs ...
     *
     */
    private IterableUtil() {}

    /**
     * Computes size of the given iterable.
     *
     *
     * @param iterable given iterable
     * @param <T> type parameter
     *
     * @return the size of the iterable
     */
    public static <T> int size(Iterable<T> iterable) {

        int counter = 0;

        for (T t : iterable) {

            counter++;
        }

        return counter;
    }


    /**
     * Converts iterable of byte array to a 2-dimensional byte array.
     *
     *
     * @param iterable given iterable of byte array
     *
     * @return byte 2-dimensional array
     */
    public static byte[][] toArray(Iterable<byte[]> iterable) {

        byte[][] result  = new byte[size(iterable)][];

        int      counter = 0;

        for (byte[] val : iterable) {

            result[counter++] = val;
        }

        return result;
    }


    /**
     * Creates an {@code Iterable} wrapper around the specified {@code Iterator} object.
     *
     * @param itr iterator for which an {@code Iterable} wrapper is requested
     * @param <T> Type of the specified iterator
     * @return an {@code Iterable} wrapper around the specified {@code Iterator} object
     */
    public static <T> Iterable<T> of(final Iterator<T> itr) {

        return new Iterable<T>() {

            @Override
            public Iterator<T> iterator() {

                return itr;
            }

        };
    }

    /**
     * Creates a new iterable by filtering {@code col} with the given {@code predicate}.
     *
     * @param col collection
     * @param predicate predicate to use for filtering
     * @param <T> type parameter
     * @return filtered collection
     */
    public static <T> Collection<T> filter(Collection<T> col, PairPredicate<T> predicate){

        Collection<T> s1 = new ArrayList<>(col);

        Collection<T> s2 = new ArrayList<>(col);

        Collection<T> result = new ArrayList<>(s1.size());

        while (!s1.isEmpty()) {

            T a = s1.iterator().next();

            for (Iterator<T> itr_s2 = s2.iterator(); itr_s2.hasNext(); ) {

                T b = itr_s2.next();

                if (predicate.apply(a, b)) {

                    s1.remove(b);

                    itr_s2.remove();
                }
            }

            result.add(a);

        }

        return result;
    }

}
